home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 029 (1987-08-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 029 (1987-08-15)(Ossowski, Stefan)(DE)(PD).adf / Robotroff / _main.c next >
C/C++ Source or Header  |  1978-08-10  |  7KB  |  276 lines

  1. /* :ts=8 bk=0
  2.  *
  3.  * Copyright (C) 1986,1987 by Manx Software Systems, Inc.
  4.  * Modified and made available for general use with permission of
  5.  * Manx Software Systems, Inc.
  6.  *
  7.  *------------------------------------------------------------------------
  8.  *
  9.  * This is special code which can be run from the Workbench or from the
  10.  * CLI.  When run from the CLI, the program detaches itself from the CLI
  11.  * and starts running in the background (giving your CLI prompt back).
  12.  * This means that all I/O from the program must be through windows
  13.  * created by the program.
  14.  *
  15.  * This startup routine correctly handles a start from the WorkBench.
  16.  * If started from the CLI, it will pass the command line arguments to the
  17.  * "child" process.  This routine also handles quoted arguments (in a
  18.  * rather primitive way).
  19.  *
  20.  * This suceesfully compiles and runs under MANX 3.20a.  Not guaranteed
  21.  * to work with other compilers.  Probably won't work with MANX 3.40,
  22.  * either (without modification).
  23.  *
  24.  * Original version by (and profuse thanks to)
  25.  *    Jim Goodnow II                86??.??
  26.  * Severely enhanced by Leo L. Schwab        8703.12
  27.  */
  28.  
  29. #include <ctype.h>
  30. #include <fcntl.h>
  31. #include <exec/alerts.h>
  32. #include <exec/memory.h>
  33. #include <libraries/dosextens.h>
  34. #include <workbench/startup.h>
  35.  
  36. #define    ERRSTR        "Improperly quoted argument.\n"
  37. #define    ERRLEN        28L
  38. #define    FATALSTR    "Fatal error on startup.\n"
  39. #define FATALEN        24L
  40.  
  41.  
  42. extern long    _Open(), _Input(), _Output(), _CurrentDir(), CreateProc();
  43. extern void    *_OpenLibrary(), *_GetMsg(), *_AllocMem(), *_FindTask();
  44.  
  45.  
  46. struct _dev {
  47.     long    fd;
  48.     short    mode;
  49. } _devtab[20];
  50.  
  51. struct _preserve {
  52.     struct Message msg;
  53.     char **av, *ab;
  54.     long cd;
  55.     int ac, al;
  56. };
  57.  
  58. long    _savsp;
  59. int    errno, Enable_Abort;
  60. void    *SysBase, *DOSBase, *MathBase, *MathTransBase;
  61.  
  62.  
  63. static struct    WBStartup *WBenchMsg;
  64. static int    argc, arglen;
  65. static char    **argv, *argbuf;
  66.  
  67. static char    unique[] = "Highly Unlikely Program Invocation Name";
  68.  
  69.  
  70. _main(alen, aptr)
  71. long alen;
  72. char *aptr;
  73. {
  74.     register struct Process *pp;
  75.     register struct CommandLineInterface *cli;
  76.     register long l;
  77.     register unsigned short c;
  78.     register char *cp;
  79.     struct FileHandle *fp;
  80.     struct MemList *mm;
  81.     struct _preserve *p;
  82.     static long cdir = 0;
  83.     long *lp;
  84.     void *sav;
  85.  
  86.     if (!(DOSBase = _OpenLibrary (DOSNAME, 0L))) {
  87.         Alert (AG_OpenLib | AO_DOSLib, 0L);
  88.         _exit (100);
  89.     }
  90.  
  91.     pp = _FindTask(0L);
  92.     if (pp->pr_CLI) {        /*  CLI invocation (first run)  */
  93.         cdir = _CurrentDir (0L);
  94.         _CurrentDir (cdir);
  95.  
  96.         /*  Parse out command line arguments  */
  97.         cli = (struct CommandLineInterface *) ((long)pp->pr_CLI << 2);
  98.         cp = (char *) ((long) cli -> cli_CommandName << 2);
  99.         arglen = *cp + alen + 2;    /* *cp is BSTR len */
  100.         argbuf = _AllocMem ((long) arglen, MEMF_PUBLIC | MEMF_CLEAR);
  101.  
  102.         strncpy (argbuf, cp+1, *cp);    /*  Copy command name  */
  103.         strcpy (argbuf + *cp, " ");    /*  Space separator  */
  104.         strncat (argbuf, aptr, (int) alen+1);    /*  Copy args  */
  105.         argbuf[*cp] = '\0';        /* Terminate full cmd name */
  106.  
  107.         for (argc=1, cp=argbuf + *cp + 1;; argc++) {
  108.             while (isspace (*cp))
  109.                 cp++;
  110.             if (*cp < ' ') {
  111.                 *cp = 0;
  112.                 break;    /*  Stop on ctl char  */
  113.             }
  114.             if (*cp == '"') {    /*  Handle quoted args  */
  115.                 *cp = ' ';    /*  Squash quote mark  */
  116.                 while ((c = *cp) && c != '"')
  117.                     cp++;
  118.                 if (!c) {    /*  No matching quote  */
  119.                     _Write (_Output(), ERRSTR, ERRLEN);
  120.                     _exit (200);
  121.                 }
  122.                 *cp++ = 0;
  123.             } else {
  124.                 while ((c = *cp) && !isspace (c))
  125.                     cp++;
  126.                 *cp++ = 0;
  127.                 if (!c)
  128.                     break;    /*  Stop at end-of-line  */
  129.             }
  130.         }
  131.  
  132.         /*  Assemble argv[] array  */
  133.         argv = _AllocMem ((long) (argc+1) * sizeof (*argv),
  134.                   MEMF_PUBLIC);
  135.         for (c=0, cp=argbuf; c<argc; c++) {
  136.             while (isspace (*cp))
  137.                 cp++;
  138.             argv[c] = cp;
  139.             cp += strlen (cp) + 1;
  140.         }
  141.         argv[c] = 0;
  142.  
  143.         /*  Preserve argument environment  */
  144.         if (!(p = _AllocMem ((long) sizeof (*p), MEMF_PUBLIC))) {
  145.             Alert (AG_NoMemory, 0L);
  146.             _exit (100);
  147.         }
  148.         p -> ac = argc;
  149.         p -> av = argv;
  150.         p -> ab = argbuf;
  151.         p -> al = arglen;
  152.         p -> cd = cdir;
  153.  
  154.         /*  Argument list finished.  Detatch program.  */
  155.         l = cli -> cli_Module;
  156.         if (!(sav = _OpenLibrary (DOSNAME, 33L))) {
  157.             /*  Malarkee for 1.1 DOS braindamage  */
  158.             lp = (long *)*((long *)*((long *)*((long *)*((long *)
  159.                 _savsp+2)+1)-3)-3)+107;
  160.             if (*lp != cli -> cli_Module) {
  161.                 _Write (_Output(), FATALSTR, FATALEN);
  162.                 _exit (300);
  163.             }
  164.         } else {
  165.             _CloseLibrary (sav);
  166.             lp = 0;
  167.         }
  168.  
  169.         /*  Prevent DOS from unloading us  */
  170.         if (lp)
  171.             *lp = 0;
  172.         cli -> cli_Module = 0;
  173. #asm
  174.         move.l    __savsp,-(sp)
  175. #endasm
  176.         _Forbid ();
  177.         PutMsg (CreateProc (unique, 0L, l, 5120L), p);
  178.         _CloseLibrary (DOSBase);
  179. #asm
  180.         move.l    (sp)+,sp
  181.         rts
  182. #endasm
  183.     } else    /*  Check if this is this is the second time through  */
  184.     if (!strcmp (pp->pr_Task.tc_Node.ln_Name, unique)) {
  185.         /*  Recover parent's arguments  */
  186.         _WaitPort (&pp -> pr_MsgPort);
  187.         p = _GetMsg (&pp -> pr_MsgPort);
  188.         argv    = p -> av;
  189.         argc    = p -> ac;
  190.         argbuf    = p -> ab;
  191.         arglen    = p -> al;
  192.         cdir    = p -> cd;
  193.         _FreeMem (p, (long) sizeof (*p));
  194.  
  195.         /*  Change process name to something reasonable  */
  196.         pp -> pr_Task.tc_Node.ln_Name = argv[0];
  197.  
  198.         /*  Convert DOS's seglist to MemList  */
  199.         lp = (long *) ((long) pp -> pr_SegList << 2);
  200.         lp = (long *) (lp[3] << 2);
  201.         sav = lp;
  202.         c = 0;
  203.         while (lp) {
  204.             lp = (long *) (*lp << 2);
  205.             c++;
  206.         }
  207.         mm = _AllocMem ((long) sizeof (struct MemList)+
  208.                 (c-1)*sizeof (struct MemEntry), MEMF_PUBLIC);
  209.         lp = sav;
  210.         mm -> ml_NumEntries = c;
  211.         c = 0;
  212.         while (lp) {
  213.             mm -> ml_me[c].me_Addr = (APTR) lp - 1;
  214.             mm -> ml_me[c].me_Length = lp[-1];
  215.             lp = (long *) (*lp << 2);
  216.             c++;
  217.         }
  218.  
  219.         /*  Add MemList to task structure to force auto-unload  */
  220.         AddTail (&((struct Task *)pp)->tc_MemEntry, mm);
  221.  
  222.         _CurrentDir (cdir);
  223.         main (argc, argv);
  224.         _exit (0);
  225.  
  226.     } else {    /*  Started from WorkBench  */
  227.         _WaitPort (&pp -> pr_MsgPort);
  228.         WBenchMsg = _GetMsg (&pp -> pr_MsgPort);
  229.         if (WBenchMsg -> sm_ArgList)
  230.             _CurrentDir (WBenchMsg -> sm_ArgList -> wa_Lock);
  231.  
  232.         if (WBenchMsg -> sm_ToolWindow)
  233.             if (_devtab[0].fd =
  234.                 _Open (WBenchMsg->sm_ToolWindow, MODE_OLDFILE)) {
  235.                 _devtab[1].fd = _devtab[2].fd = _devtab[0].fd;
  236.                 _devtab[0].mode = 0x8000;
  237.                 _devtab[1].mode = _devtab[2].mode = 0x8001;
  238.                 fp=(struct FileHandle *) (_devtab[0].fd << 2);
  239.                 pp -> pr_ConsoleTask = (APTR) fp -> fh_Type;
  240.             }
  241.  
  242.         main (0, WBenchMsg);
  243.         _exit (0);
  244.     }
  245. }
  246.  
  247. void (*_cln)() = 0;
  248.  
  249. _exit (code)
  250. {
  251.     int fd;
  252.  
  253.     for (fd = 0; fd < 20; fd++)
  254.         close (fd);
  255.     if (_cln)
  256.         (*_cln)();
  257.  
  258.     if (MathTransBase)    _CloseLibrary (MathTransBase);
  259.     if (MathBase)        _CloseLibrary (MathBase);
  260.     if (DOSBase)        _CloseLibrary (DOSBase);
  261.  
  262.     if (!WBenchMsg) {    /*  Free the argument list  */
  263.         _FreeMem (argbuf, (long) arglen);
  264.         if (argv)
  265.             _FreeMem (argv, (long) (argc+1) * sizeof (*argv));
  266.     } else {
  267.         _Forbid ();
  268.         _ReplyMsg (WBenchMsg);
  269.     }
  270. #asm
  271.         move.l    8(a5),d0    ; Get return code
  272.         move.l    __savsp,sp    ; Restore original stack pointer
  273.         rts            ; Bye-bye!
  274. #endasm
  275. }
  276.